﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Threading;
using System.Windows.Threading;
using System.Globalization;

namespace WeatherFrame
{
    public class WeatherItem : INotifyPropertyChanged
    {

        public string TimePeriod
        {
            get
            {
                if (!date.HasValue) return null;
                var dateVal = date.Value;
                string dayString = dateVal.ToString("dddd", CultureInfo.InvariantCulture).ToLowerInvariant();
                DateTime now = DateTime.Now;
                if (dateVal.DayOfYear == now.DayOfYear)
                {
                    dayString = "today"; 
                    if (IsNight) dayString = "tonight";
                }
                if (dateVal.DayOfYear == now.DayOfYear + 1) dayString = "tomorrow";
                return dayString;
            } 
        }

        public string TimePeriodShort
        {
            get
            {
                if (!date.HasValue) return null;
                var dateVal = date.Value;
                string dayString = dateVal.ToString("ddd", CultureInfo.InvariantCulture).ToLowerInvariant();
                DateTime now = DateTime.Now;
                if (dateVal.DayOfYear == now.DayOfYear)
                {
                    dayString = "today";
                    if (IsNight) dayString = "tonight";
                }
                //if (dateVal.DayOfYear == now.DayOfYear + 1) dayString = "tomorrow";
                return dayString;
            }
        }


        bool IsNight
        {
            get
            {
                if (!date.HasValue) return false;
                DateTime now = DateTime.Now;
                if (date.Value.DayOfYear != now.DayOfYear) return false;
                return now.Hour > 16;
            }
        }

        public void SetTo(WeatherItem item)
        {
            IsWaitingForWeather = item.IsWaitingForWeather;
            ErrorText = item.ErrorText;
            Location = item.Location;
            Parent = item.Parent;
            Date = item.Date;
            WeatherCondition = item.WeatherCondition;
            Image = item.Image;
            ImageUri = item.ImageUri;
            ImageTitle = item.ImageTitle;
            ImageCredit = item.ImageCredit;
            //ImageTitle = "this is a really, really long image title to test to see what happens";
            //ImageCredit = "this is a really, really long image credit to test to see what happens";
            MinTempC = item.MinTempC;
            MaxTempC = item.MaxTempC;
            MinTempF = item.MinTempF;
            MaxTempF = item.MaxTempF;
            WindDirection = item.WindDirection;
            WindspeedMph = item.WindspeedMph;
            PrecipitationMm = item.PrecipitationMm;
        }

        bool isWaitingForWeather = true;
        public bool IsWaitingForWeather
        {
            get { return isWaitingForWeather; }

            set
            {
                if (IsWaitingForWeather == value) return;
                isWaitingForWeather = value;
                NotifyPropertyChanged("IsWaitingForWeather");
            }
        }

        Visibility isVisible = Visibility.Visible;
        public Visibility IsVisible
        {
            get { return isVisible; }

            set
            {
                if (isVisible == value) return;
                isVisible = value;
                NotifyPropertyChanged("IsVisible");
            }
        }

        string errorText = null;
        public string ErrorText
        {
            get { return errorText; }

            set
            {
                if (errorText == value) return;
                errorText = value;
                NotifyPropertyChanged("ErrorText");
                NotifyPropertyChanged("IsErrorState");
            }
        }

        public bool IsErrorState
        {
            get { return errorText != null; }
        }

        string imageUri = null;//"/SplashScreenImage2.jpg";
        public string ImageUri
        {
            get{ return imageUri; }

            set {
                imageUri = value;
                NotifyPropertyChanged("ImageUri");
            }
        }

        string imageCredit;//"credit";
        public string ImageCredit
        {
            get{ return imageCredit; }

            set
            {
                imageCredit = value;
                NotifyPropertyChanged("ImageCredit");
            }
        }

        string imageTitle;//"this is a really long title";
        public string ImageTitle
        {
            get { return imageTitle; }

            set
            {
                imageTitle = value;
                NotifyPropertyChanged("ImageTitle");
            }
        }

        public string IconPath
        {
            get
            {
                if (weatherCondition == null) return null;
                string key = GetImageKey();
                if (key == null) return null;
                //key = key.Replace("Night", "");
                //return string.Format("../Icons/{0}.png", key);
                return key;
            }
        }

        private string GetImageKey()
        {
            if (weatherCondition == null) return null;
            string key = weatherCondition.CondKey;
            if (key == null) return null;
            if (IsNight)
            {
                key = key.Replace("Sun", "Moon");
            }
            return key;
        }

        WeatherCondition weatherCondition;// = WeatherCondition.FromWeatherCode(113);
        public WeatherCondition WeatherCondition
        {
            get { return weatherCondition; }

            set
            {
                weatherCondition = value;
                NotifyPropertyChanged("WeatherCondition");
                NotifyPropertyChanged("IconPath");
            }
        }

        internal void SetImageFromCondition()
        {
            if (weatherCondition == null)
            {
                ImageCredit = null;
                ImageTitle = null;
                ImageUri = null;
                return;
            }
            string key = GetImageKey();
            int hash = Math.Abs(Location.Name.GetHashCode() + Date.GetHashCode() + DateTime.Now.Date.GetHashCode());
            if (App.ViewModel.ImageIndex == null) return;
            image = App.ViewModel.ImageIndex.GetImageForConditionKey(key, hash);
            if (image == null) return;
            ImageUri = image.SmallUri;
            imageCredit = image.Credit;
            ImageTitle = image.Title;
        }

        ConditionImage image;
        public ConditionImage Image
        {
            get { 
                return image; 
            }
            set { 
                image = value; 
            }
        }

        DateTime? date;
        public DateTime? Date
        {
            get { return date; }

            set
            {
                if (date == value) return;
                date = value;
                NotifyPropertyChanged("Date");
                NotifyPropertyChanged("TimePeriod");
                NotifyPropertyChanged("TimePeriodShort");
            }
        }

        Location loc;
        public Location Location
        {
            get { return loc; }
            set {
                if (loc == value) return;
                loc = value; 
                NotifyPropertyChanged("Location");
                NotifyPropertyChanged("LocationText"); 
            }
        }
        public string LocationText { get {
            if ((Location == null) || (Location.Name == null)) return null;
            return Location.Name.ToUpperInvariant(); 
        } }

        int minTempC = int.MinValue;
        public int MinTempC
        {
            get { return minTempC; }

            set
            {
                minTempC = value;
                NotifyPropertyChanged("MinTempC");
                NotifyPropertyChanged("TempTextMax");
            }
        }

        int maxTempC = -1;
        public int MaxTempC
        {
            get { return maxTempC; }

            set
            {
                maxTempC = value;
                NotifyPropertyChanged("MaxTempC");
                NotifyPropertyChanged("TempTextMax");
            }
        }

        int minTempF = -1;
        public int MinTempF
        {
            get { return minTempF; }

            set
            {
                minTempF = value;
                NotifyPropertyChanged("MinTempF");
                NotifyPropertyChanged("TempTextMin");
            }
        }

        int maxTempF = -1;
        public int MaxTempF
        {
            get { return maxTempF; }

            set
            {
                maxTempF = value;
                NotifyPropertyChanged("MaxTempF");
                NotifyPropertyChanged("TempTextMax");
            }
        }

        public string TempTextMin
        {
            get
            {
                if (MinTempC == int.MinValue) return "";
                if (App.ViewModel.UseCelsius)
                {
                    return MinTempC.ToString();// +"°C";
                }
                else
                {
                    return MinTempF.ToString();// +"°F";
                }
            }
        }

        public string TempTextMax
        {
            get
            {
                if (MinTempC == int.MinValue) return "";
                if (App.ViewModel.UseCelsius)
                {
                    //if (MinTempC == MaxTempC) return MinTempC + "°C";
                    return MaxTempC.ToString();// +"°C";
                }
                else
                {
                    //if (MinTempF == MaxTempF) return MinTempF + "°F";
                    return MaxTempF.ToString();// +"°F";
                }
            }
        }

        double windspeedMph = 0;
        public double WindspeedMph
        {
            get { return windspeedMph; }

            set
            {
                windspeedMph = value;
                NotifyPropertyChanged("WindspeedMph");
            }
        }

        string windDirection;
        public string WindDirection
        {
            get { return windDirection; }

            set
            {
                windDirection = value;
                NotifyPropertyChanged("WindDirection");
            }
        }

        double precipitationMm = 0;
        public double PrecipitationMm
        {
            get { return precipitationMm; }

            set
            {
                precipitationMm = value;
                NotifyPropertyChanged("PrecipitationMm");
            }
        }


        public WeatherModel Parent { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;
        internal void NotifyPropertyChanged(String propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler==null) return;            
            var dispatcher = System.Windows.Deployment.Current.Dispatcher;
            dispatcher.BeginInvoke(() =>
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            });
        }


        internal void Clear()
        {
            Date = null;
            MinTempC = int.MinValue;
            windspeedMph = 0;
            precipitationMm = 0;
            windDirection = null;
            Location = null;
            Image = null;
            ImageCredit = null;
            ImageUri = null;
            imageTitle = null;
            WeatherCondition = null;
            IsWaitingForWeather = true;
            ErrorText = null;
            OnTempChanged();
        }

        internal void OnTempChanged()
        {
            NotifyPropertyChanged("TempTextMax");
            NotifyPropertyChanged("TempTextMin");
        }
    }
}